#!/usr/bin/env bash

# 严格模式设置
set -euo pipefail
IFS=$'\n\t'

# 信号处理
trap 'echo "Error: Exiting due to an error." >&2; exit 1' ERR
trap 'echo "Error: Script interrupted by user." >&2; exit 1' INT
trap 'echo "Error: Script terminated by signal." >&2; exit 1' TERM

# 定义只读变量
readonly SCRIPT_NAME=$(basename "$0")
readonly ERROR_LOG="error.log"
readonly DOWN_HOSTS_FILE="down_hosts.txt"
readonly VERSION="1.0"

# 函数：显示使用方法
show_usage() {
    echo "Usage: sh $SCRIPT_NAME <filename>"
    echo "  <filename>: Path to the file containing IP addresses to check"
    echo
    echo "Version: $VERSION"
    echo "This script checks the availability of IP addresses listed in the input file."
    exit 1
}

# 函数：记录错误
log_error() {
    echo "$1" >>"$ERROR_LOG"
    echo "Error: $1" >&2
}

# 函数：验证IP地址
validate_ip() {
    local ip=$1
    local re='^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
    [[ $ip =~ $re ]] && [[ ! $ip =~ ^(0\.|255\.|127\.) ]] && [[ ${ip##*.} != 0 ]]
}

# 函数：验证IP地址列表
validate_ip_addresses() {
    local file=$1
    local line_number=0
    local valid_ips=0
    local total_lines=0
    local empty_lines=0

    echo "Starting IP address validation..."

    while IFS= read -r line || [[ -n "$line" ]]; do
        line_number=$((line_number + 1))
        total_lines=$((total_lines + 1))
        # 去除行首尾的空白字符
        # line=$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
        if [[ -z "$line" ]]; then
            log_error "Empty line detected (Line $line_number)"
            empty_lines=$((empty_lines + 1))
        elif ! validate_ip "$line"; then
            log_error "Invalid IP address: $line (Line $line_number)"
        else
            valid_ips=$((valid_ips + 1))
        fi
    done <"$file"
    echo "**************************************************************"
    echo "* IP address validation completed."
    echo "* Total lines processed: $total_lines"
    echo "* Valid IP addresses found: $valid_ips"
    echo "* Empty lines detected: $empty_lines"
    echo "* Invalid entries: $((total_lines - valid_ips - empty_lines))"
    echo "**************************************************************"
}

# 函数：检查主机可达性
check_hosts_with_ping() {
    local file=$1
    local total_ips
    total_ips=$(wc -l <"$file")
    local counter=0
    local down_hosts=0
    local line_number=0
    true >"$DOWN_HOSTS_FILE"

    echo "Starting ping tests for $total_ips IP addresses..."

    while IFS= read -r ip || [[ -n "$ip" ]]; do
        counter=$((counter + 1))
        line_number=$((line_number + 1))
        printf "Testing IP %d/%d: %s\r" "$counter" "$total_ips" "$ip"
        if ! timeout 2 ping -c 2 -W 1 "$ip" &>/dev/null; then
            echo "$ip" >>"$DOWN_HOSTS_FILE"
            log_error "Host unreachable: $ip (Line $line_number)"
            down_hosts=$((down_hosts + 1))
        fi
    done <"$file"

    echo -e "\nPing tests completed."
    echo "Total IP addresses tested: $total_ips"
    echo "Down hosts detected: $down_hosts"
}

# 主程序
main() {
    echo "Script started: $(date)"

    # 检查参数
    if [[ $# -ne 1 ]]; then
        show_usage
    fi

    local input_file=$1

    # 检查输入文件
    if [[ ! -f "$input_file" || ! -r "$input_file" ]]; then
        echo "Error: File '$input_file' not found or not readable." >&2
        exit 1
    fi

    # 清空错误日志
    true >"$ERROR_LOG"

    echo "IP addresses are being checked..."
    echo "Errors will be logged to $ERROR_LOG"

    # 验证IP地址
    validate_ip_addresses "$input_file"

    # 检查错误日志
    if [[ -s "$ERROR_LOG" ]]; then
        echo "Errors were found in the IP list. Please check the error log: $ERROR_LOG" >&2
        exit 1
    fi

    # 执行ping测试
    check_hosts_with_ping "$input_file"

    # 检查DOWN_HOSTS_FILE是否存在并且可读
    if [[ ! -f "${DOWN_HOSTS_FILE}" || ! -r "${DOWN_HOSTS_FILE}" ]]; then
        echo >&2 "Error: The file ${DOWN_HOSTS_FILE} does not exist or is not readable."
        exit 1
    fi

    # 检查DOWN_HOSTS_FILE是否为空
    if ! grep -q '[^[:space:]]' "${DOWN_HOSTS_FILE}"; then
        echo "All hosts are up. No down hosts detected."
    else
        echo "Down hosts detected. Please check the down hosts list: $DOWN_HOSTS_FILE"
        echo "Total down hosts: $(wc -l <"$DOWN_HOSTS_FILE")"
        echo "Down hosts:"
        while IFS= read -r line || [[ -n "$line" ]]; do
            echo "  $line"
        done <"${DOWN_HOSTS_FILE}"
    fi

    echo "Script completed: $(date)"
}

# 执行主程序
main "$@"
